/*
 * Project: push-center-service-impl
 * 
 * File Created at 2014-10-9
 * 
 * Copyright 2012 Greenline.com Corporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Greenline Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Greenline.com.
 */
package com.greenline.push.service.core.send;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.greenline.message.biz.service.share.sms.SMSParamDTO;
import com.greenline.message.biz.service.share.sms.SMSParamsDTO;
import com.greenline.message.biz.service.share.sms.SMSResultDTO;
import com.greenline.message.biz.service.share.sms.SmsService;
import com.greenline.push.core.enums.Channels;
import com.greenline.push.core.enums.MsgSendType;
import com.greenline.push.core.enums.Tasks;
import com.greenline.push.core.pushcenter.GroupUserManager;
import com.greenline.push.service.core.item.AppPacket;
import com.greenline.push.service.core.item.Packet;
import com.greenline.push.service.core.send.base.AbstractSender;
import com.greenline.push.service.core.send.base.AppPacketHandler;
import com.greenline.push.service.core.tmpl.GroupAppCache;
import com.greenline.push.service.core.user.UserConnact;
import com.greenline.push.service.core.utils.Constants;

/**
 * 
 * @Type SMSSender
 * @Desc 发送sms消息
 * @author shuai.zuo
 * @date 2014年10月28日
 * @Version V1.0
 */
public class SMSSender extends AbstractSender {
    @Resource
    private SmsService smshessianservice;
    @Autowired
    private GroupUserManager groupUserService;
    @Resource
    private GroupAppCache groupAppCache;
    @Resource
    private AppPacketHandler packetHandler;

    private final Logger logger = Constants.LOG_PROCESS;

    @Override
    public Channels supportChannel() {
        return Channels.sms;
    }

    @Override
    protected boolean doSend(Packet packet) {
        AppPacket appPacket = (AppPacket) packet;

        logger.info(String.format(
                "{smssender收到数据}:准备发送***domainId:[%s].tempId:[%s].type:[%s],extparam-context:[%s-%s],source:[%s],retryId:[%s],thread:[%s]",
                appPacket.getDomainId(), appPacket.getTemplateId(), appPacket.getType(), appPacket.getExtParam(), appPacket.getContext(),
                appPacket.getSource(), appPacket.getDbRetryId(), Thread.currentThread().getName()));
        //
        boolean succ = false;
        if (MsgSendType.POINT.getType() == appPacket.getType()) {
            // succ = sendSms(mobile, context);
            succ = sendPoint(appPacket);
        } else if (MsgSendType.GROUP.getType() == appPacket.getType()) {
            sendGroup(appPacket);
        } else if (MsgSendType.UPLOAD.getType() == appPacket.getType() || MsgSendType.CONDITIONS.getType() == appPacket.getType()
                || MsgSendType.DOMAIN.getType() == appPacket.getType()) {
            // upload 或者 condition 类型 可以调用第三方按组发送
            this.sendList(appPacket);
        } else {
            // sendSmsGroup(appPacket);
            packetHandler.afterSendOperation(appPacket, succ, true);
        }

        // //测试代码
        // boolean succ = true;
        // try {
        // Thread.sleep(80l);
        // } catch (InterruptedException e) {
        // // TODO Auto-generated catch block
        // e.printStackTrace();
        // }
        // super.afterSendOperation(appPacket, succ);
        return succ;
    }

    private void sendList(AppPacket appPacket) {
        String methodName = "{smsSender.sendList}";
        Long retryId = appPacket.getDbRetryId();
        List<String> uids = getUserIdsByRetryId(retryId);
        // null case
        if (uids == null) {
            logger.error(String.format("%s发送失败,apppacket下没有取到用户.retryId:%s.context:%s", methodName, retryId, appPacket.getContext()));
            packetHandler.afterSendOperation(appPacket, false, true);
            return;
        }
        // set uid
        appPacket.setUserids(uids.toString());

        logger.debug(String.format("%s批量发送sms消息.uidlist:%s.contenxt:%s", methodName, uids.toString(), appPacket.getContext()));
        SMSParamsDTO paramsdto = new SMSParamsDTO();
        paramsdto.setPriority(8);
        Set<String> phones = new HashSet<String>();
        for (String userId : uids) {
            // 转化成point
            Long uid = Long.valueOf(userId);
            UserConnact ucontact = getUserConnact(uid);
            if (ucontact == null)
                continue;
            // build
            phones.add(ucontact.getMobile());
        }
        if (phones.isEmpty()) {
            // delete
            packetHandler.afterSendOperation(appPacket, false, true);
            // log
            logger.warn(String.format("%s批量发送sms消息获取到mobile列表为空,不再进行下一步处理.uidlist:[%s].content:[%s],retryId:[%s]", methodName,
                    uids.toString(), appPacket.getExtParam(), appPacket.getDbRetryId()));
            return;
        }
        paramsdto.setTelphones(phones);
        boolean result = sendmessages(paramsdto);
        //
        logger.info(String.format("{%s推送结果}response:[%s],context:[%s],users:[%s],phones:[%s],retryId:[%s]", methodName, result,
                appPacket.getContext(), uids, phones, appPacket.getDbRetryId()));
        //
        packetHandler.afterSendOperation(appPacket, result);
    }

    private boolean sendPoint(AppPacket appPacket) {
        String methodName = "{smsSender.sendPoint}";
        String mobile = appPacket.getDeviceToken();
        String context = appPacket.getContext();
        logger.debug(String.format("{smssender发送短信}******接受人%s.内容:%s", mobile, context));
        // do send
        boolean success = false;
        SMSParamDTO smsdto = new SMSParamDTO(mobile, context);
        smsdto.setPriority(8);// 设置优先级 0到4 低优先级 ； 5到9高优先级 ；portal使用8
        SMSResultDTO res;
        try {
            res = sendIsNext(smsdto);
            success = res.isSuccess();
            logger.info(String.format("{%s推送结果}.response:[%s].context:[%s],user:[%s-%s],retryId:[%s]", methodName, success,
                    appPacket.getContext(), appPacket.getRecvUserId(), mobile, appPacket.getDbRetryId()));
        } catch (Exception e) {
            logger.error(String.format("{sendPoint**sms推送异常}message:%s,context:%s,retryId:[%s]", e.getMessage(), context,
                    appPacket.getDbRetryId()));
            e.printStackTrace();
        }
        //
        packetHandler.afterSendOperation(appPacket, success);
        return success;

    }

    private void sendGroup(AppPacket appPacket) {
        logger.debug(String.format("{sms**sendGroup开始推送}context:%s,gid:%s", appPacket.getContext(), appPacket.getRecvUserId()));

        String relativeGroupId = groupAppCache.loadByGroupId(appPacket.getAppChannelId(), appPacket.getRecvUserId());
        if (StringUtils.isBlank(relativeGroupId)) {
            Long gid = appPacket.getRecvUserId();
            List<Long> userIds = getUserIdsbyGid(gid);
            for (Long userId : userIds) {
                // 转化成point
                UserConnact ucontact = getUserConnact(userId);
                if (ucontact == null)
                    continue;
                // send...
                appPacket.setRecvUserId(userId);
                appPacket.setDeviceToken(ucontact.getMobile());
                sendPoint(appPacket);
            }
        } else {
            // send group directly
            logger.error(String.format("{sms调用群发失败.}原因:%s.gid:%s,appchannelId:%s", "没有快捷群发接口", appPacket.getRecvUserId(),
                    appPacket.getAppChannelId()));
        }
    }

    private boolean sendmessages(SMSParamsDTO smsdto) {
        Map<String, SMSResultDTO> ret;
        try {
            ret = smshessianservice.sendMessages(smsdto);
        } catch (Exception e) {
            return false;
        }
        for (Entry<String, SMSResultDTO> entry : ret.entrySet()) {
            SMSResultDTO result = entry.getValue();
            logger.debug(String.format("{短信批量发送结果}%s-%s,发送内容：%s", entry.getKey(), result.isSuccess(), smsdto.getContent()));
        }
        return true;
    }

    private SMSResultDTO sendIsNext(SMSParamDTO smsdto) {
        SMSResultDTO ret = smshessianservice.send(smsdto);
        logger.debug(String.format("{短信发送结果}%s,发送内容：%s", JSON.toJSONString(ret), JSON.toJSONString(smsdto)));
        if (!ret.isSuccess()) {
            logger.error("第一次发送没有成功。" + ret.getMessage());
            smshessianservice.send(smsdto);
        }
        return ret;
    }

    @Override
    protected Tasks getTaskType() {
        return Tasks.FETCH_RETRY_SMS;
    }

    @Override
    protected String getQueueName() {
        return "短信处理队列";
    }

    @Override
    protected Tasks getFullTaskType() {
        return Tasks.FETCH_RETRY_SMS_FULL;
    }

    @Override
    protected String getFullQueueName() {
        return "全量短信处理队列";
    }

}
